bitkeeper revision 1.645.1.1 (3fd9f02bxWKGgV_bPDcD98xGu_WfmA)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 12 Dec 2003 16:43:23 +0000 (16:43 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 12 Dec 2003 16:43:23 +0000 (16:43 +0000)
Many files:
  Update the VBD interface.

tools/examples/createlinuxdom.py
tools/examples/mynewdom.py
tools/xc/lib/xc.h
tools/xc/lib/xc_vbd.c
tools/xc/py/Xc.c
xen/drivers/block/xen_block.c
xen/drivers/block/xen_vbd.c
xen/include/hypervisor-ifs/vbd.h
xen/include/xeno/vbd.h

index 57b2b0760ab4acf2e9480e9ab6c71743bf442004..d01a2ea0b7c7e80cf2d81bfe80ccb99ab55733d8 100755 (executable)
@@ -77,11 +77,11 @@ if root_partn:
         print "Error creating root VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
-    if xc.vbd_add_extent( dom=id,
-                          vbd=root_info[0],
-                          device=root_info[1],
-                          start_sector=root_info[2],
-                          nr_sectors=root_info[3] ):
+    if xc.vbd_grow( dom=id,
+                    vbd=root_info[0],
+                    device=root_info[1],
+                    start_sector=root_info[2],
+                    nr_sectors=root_info[3] ):
         print "Error populating root VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
@@ -91,11 +91,11 @@ if usr_partn:
         print "Error creating usr VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
-    if xc.vbd_add_extent( dom=id,
-                          vbd=usr_info[0],
-                          device=usr_info[1],
-                          start_sector=usr_info[2],
-                          nr_sectors=usr_info[3] ):
+    if xc.vbd_grow( dom=id,
+                    vbd=usr_info[0],
+                    device=usr_info[1],
+                    start_sector=usr_info[2],
+                    nr_sectors=usr_info[3] ):
         print "Error populating usr VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
index b3df7853bf9c2f9d48718c4c723f67462fadaaf6..29c8a35419b9c93b0aa74838c8f266d4512a861b 100755 (executable)
@@ -83,11 +83,11 @@ if root_partn:
         print "Error creating root VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
-    if xc.vbd_add_extent( dom=id,
-                          vbd=root_info[0],
-                          device=root_info[1],
-                          start_sector=root_info[2],
-                          nr_sectors=root_info[3] ):
+    if xc.vbd_grow( dom=id,
+                    vbd=root_info[0],
+                    device=root_info[1],
+                    start_sector=root_info[2],
+                    nr_sectors=root_info[3] ):
         print "Error populating root VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
@@ -97,11 +97,11 @@ if usr_partn:
         print "Error creating usr VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
-    if xc.vbd_add_extent( dom=id,
-                          vbd=usr_info[0],
-                          device=usr_info[1],
-                          start_sector=usr_info[2],
-                          nr_sectors=usr_info[3] ):
+    if xc.vbd_grow( dom=id,
+                    vbd=usr_info[0],
+                    device=usr_info[1],
+                    start_sector=usr_info[2],
+                    nr_sectors=usr_info[3] ):
         print "Error populating usr VBD"
         xc.domain_destroy ( dom=id )
         sys.exit()
index 6b025a1c8b9b1833c1f956c9c9c2f99ee8a9e5a5..246d9cfbf93ea0ee0cc6891c9504702d3c8af861 100644 (file)
@@ -34,6 +34,9 @@ int xc_domain_stop(int xc_handle,
 int xc_domain_destroy(int xc_handle, 
                       unsigned int domid, 
                       int force);
+int xc_domain_pincpu(int xc_handle,
+                     unsigned int domid,
+                     int cpu);
 int xc_domain_getinfo(int xc_handle,
                       unsigned int first_domid, 
                       unsigned int max_doms,
@@ -93,6 +96,11 @@ typedef struct {
     unsigned long  nr_sectors;
 } xc_vbd_t;
 
+typedef struct {
+    unsigned short real_device;
+    unsigned long  start_sector;
+    unsigned long  nr_sectors;
+} xc_vbdextent_t;
 
 int xc_vbd_create(int xc_handle,
                   unsigned int domid, 
@@ -101,18 +109,24 @@ int xc_vbd_create(int xc_handle,
 int xc_vbd_destroy(int xc_handle,
                    unsigned int domid, 
                    unsigned short vbdid);
-int xc_vbd_add_extent(int xc_handle,
+int xc_vbd_grow(int xc_handle,
+                unsigned int domid, 
+                unsigned short vbdid,
+                xc_vbdextent_t *extent);
+int xc_vbd_shrink(int xc_handle,
+                  unsigned int domid, 
+                  unsigned short vbdid);
+int xc_vbd_setextents(int xc_handle,
                       unsigned int domid, 
                       unsigned short vbdid,
-                      unsigned short real_device,
-                      unsigned long start_sector,
-                      unsigned long nr_sectors);
-int xc_vbd_delete_extent(int xc_handle,
-                         unsigned int domid, 
-                         unsigned short vbdid,
-                         unsigned short real_device,
-                         unsigned long start_sector,
-                         unsigned long nr_sectors);
+                      unsigned int nr_extents,
+                      xc_vbdextent_t *extents);
+int xc_vbd_getextents(int xc_handle,
+                      unsigned int domid, 
+                      unsigned short vbdid,
+                      unsigned int max_extents,
+                      xc_vbdextent_t *extents,
+                      int *writeable);
 int xc_vbd_probe(int xc_handle,
                  unsigned int domid,
                  unsigned int max_vbds,
index 914206c0f43d2c8171bdf26da353d5a492a5aee2..b309ed28d2f6cb3cb555466303ce223c4569e582 100644 (file)
@@ -35,42 +35,129 @@ int xc_vbd_destroy(int xc_handle,
 }
 
 
-int xc_vbd_add_extent(int xc_handle,
-                      unsigned int domid, 
-                      unsigned short vbdid,
-                      unsigned short real_device,
-                      unsigned long start_sector,
-                      unsigned long nr_sectors)
+int xc_vbd_grow(int xc_handle,
+                unsigned int domid, 
+                unsigned short vbdid,
+                xc_vbdextent_t *extent)
 {
     block_io_op_t op; 
-    op.cmd = BLOCK_IO_OP_VBD_ADD
-    op.u.add_params.domain  = domid; 
-    op.u.add_params.vdevice = vbdid;
-    op.u.add_params.extent.device       = real_device; 
-    op.u.add_params.extent.start_sector = start_sector;
-    op.u.add_params.extent.nr_sectors   = nr_sectors;
+    op.cmd = BLOCK_IO_OP_VBD_GROW
+    op.u.grow_params.domain  = domid; 
+    op.u.grow_params.vdevice = vbdid;
+    op.u.grow_params.extent.device       = extent->real_device; 
+    op.u.grow_params.extent.start_sector = extent->start_sector;
+    op.u.grow_params.extent.nr_sectors   = extent->nr_sectors;
     return do_block_io_op(xc_handle, &op);
 }
 
 
-int xc_vbd_delete_extent(int xc_handle,
-                         unsigned int domid, 
-                         unsigned short vbdid,
-                         unsigned short real_device,
-                         unsigned long start_sector,
-                         unsigned long nr_sectors)
+int xc_vbd_shrink(int xc_handle,
+                  unsigned int domid, 
+                  unsigned short vbdid)
 {
     block_io_op_t op; 
-    op.cmd = BLOCK_IO_OP_VBD_REMOVE; 
-    op.u.add_params.domain  = domid; 
-    op.u.add_params.vdevice = vbdid;
-    op.u.add_params.extent.device       = real_device; 
-    op.u.add_params.extent.start_sector = start_sector;
-    op.u.add_params.extent.nr_sectors   = nr_sectors;
+    op.cmd = BLOCK_IO_OP_VBD_SHRINK; 
+    op.u.shrink_params.domain  = domid; 
+    op.u.shrink_params.vdevice = vbdid;
     return do_block_io_op(xc_handle, &op);
 }
 
 
+int xc_vbd_setextents(int xc_handle,
+                      unsigned int domid, 
+                      unsigned short vbdid,
+                      unsigned int nr_extents,
+                      xc_vbdextent_t *extents)
+{
+    int           i, rc;
+    block_io_op_t op;
+    xen_extent_t *real_extents = NULL;
+
+    if ( nr_extents != 0 )
+    {
+        real_extents = malloc(nr_extents * sizeof(xc_vbdextent_t));
+        if ( (real_extents == NULL) || 
+             (mlock(real_extents, nr_extents * sizeof(xc_vbdextent_t)) != 0) )
+        {
+            if ( real_extents != NULL )
+                free(real_extents);
+            return -ENOMEM;
+        }
+
+        for ( i = 0; i < nr_extents; i++ )
+        {
+            real_extents[i].device       = extents[i].real_device;
+            real_extents[i].start_sector = extents[i].start_sector;
+            real_extents[i].nr_sectors   = extents[i].nr_sectors;
+        }
+    }
+
+    op.cmd = BLOCK_IO_OP_VBD_SET_EXTENTS;
+    op.u.setextents_params.domain     = domid;
+    op.u.setextents_params.vdevice    = vbdid;
+    op.u.setextents_params.nr_extents = nr_extents;
+    op.u.setextents_params.extents    = real_extents;
+    rc = do_block_io_op(xc_handle, &op);
+
+    if ( real_extents != NULL )
+    {
+        (void)munlock(real_extents, nr_extents * sizeof(xc_vbdextent_t));
+        free(real_extents);
+    }
+
+    return rc;
+}
+
+
+int xc_vbd_getextents(int xc_handle,
+                      unsigned int domid, 
+                      unsigned short vbdid,
+                      unsigned int max_extents,
+                      xc_vbdextent_t *extents,
+                      int *writeable)
+{
+    int           i, rc;
+    block_io_op_t op;
+    xen_extent_t *real_extents = malloc(max_extents * sizeof(xc_vbdextent_t));
+
+    if ( (real_extents == NULL) || 
+         (mlock(real_extents, max_extents * sizeof(xc_vbdextent_t)) != 0) )
+    {
+        if ( real_extents != NULL )
+            free(real_extents);
+        return -ENOMEM;
+    }
+
+    op.cmd = BLOCK_IO_OP_VBD_INFO;
+    op.u.info_params.domain     = domid;
+    op.u.info_params.vdevice    = vbdid;
+    op.u.info_params.maxextents = max_extents;
+    op.u.info_params.extents    = real_extents;
+    rc = do_block_io_op(xc_handle, &op);
+
+    (void)munlock(real_extents, max_extents * sizeof(xc_vbdextent_t));
+
+    if ( rc >= 0 )
+    {
+        for ( i = 0; i < op.u.info_params.nextents; i++ )
+        {
+            extents[i].real_device  = real_extents[i].device;
+            extents[i].start_sector = real_extents[i].start_sector;
+            extents[i].nr_sectors   = real_extents[i].nr_sectors;
+        }
+
+        if ( writeable != NULL )
+            *writeable = !!(op.u.info_params.mode & VBD_MODE_W);
+
+        rc = op.u.info_params.nextents;
+    }
+
+    free(real_extents);
+
+    return rc;
+}
+
+
 int xc_vbd_probe(int xc_handle,
                  unsigned int domid,
                  unsigned int max_vbds,
index 0676bd137b9a15f7d6bbcee8c4fd595c0f0b8123..e24a6911722b4c7fb911bd3be70b0b417bef645f 100644 (file)
@@ -387,52 +387,159 @@ static PyObject *pyxc_vbd_destroy(PyObject *self,
     return PyInt_FromLong(ret);
 }
 
-static PyObject *pyxc_vbd_add_extent(PyObject *self,
-                                     PyObject *args,
-                                     PyObject *kwds)
+static PyObject *pyxc_vbd_grow(PyObject *self,
+                               PyObject *args,
+                               PyObject *kwds)
 {
     XcObject *xc = (XcObject *)self;
 
-    unsigned int  dom, vbd, device;
-    unsigned long start_sector, nr_sectors;
-    int           ret;
+    unsigned int   dom, vbd;
+    xc_vbdextent_t extent;
+    int            ret;
 
     static char *kwd_list[] = { "dom", "vbd", "device", 
                                 "start_sector", "nr_sectors", NULL };
 
     if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiill", kwd_list, 
-                                      &dom, &vbd, &device, 
-                                      &start_sector, &nr_sectors) )
+                                      &dom, &vbd, 
+                                      &extent.real_device, 
+                                      &extent.start_sector, 
+                                      &extent.nr_sectors) )
         return NULL;
 
-    ret = xc_vbd_add_extent(xc->xc_handle, dom, vbd, device, 
-                            start_sector, nr_sectors);
+    ret = xc_vbd_grow(xc->xc_handle, dom, vbd, &extent);
     
     return PyInt_FromLong(ret);
 }
 
-static PyObject *pyxc_vbd_delete_extent(PyObject *self,
-                                        PyObject *args,
-                                        PyObject *kwds)
+static PyObject *pyxc_vbd_shrink(PyObject *self,
+                                 PyObject *args,
+                                 PyObject *kwds)
 {
     XcObject *xc = (XcObject *)self;
 
-    unsigned int  dom, vbd, device;
-    unsigned long start_sector, nr_sectors;
+    unsigned int  dom, vbd;
     int           ret;
 
-    static char *kwd_list[] = { "dom", "vbd", "device", 
-                                "start_sector", "nr_sectors", NULL };
+    static char *kwd_list[] = { "dom", "vbd", NULL };
 
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiill", kwd_list, 
-                                      &dom, &vbd, &device, 
-                                      &start_sector, &nr_sectors) )
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
+                                      &dom, &vbd) )
         return NULL;
 
-    ret = xc_vbd_delete_extent(xc->xc_handle, dom, vbd, device, 
-                               start_sector, nr_sectors);
+    ret = xc_vbd_shrink(xc->xc_handle, dom, vbd);
+    
+    return PyInt_FromLong(ret);
+}
+
+static PyObject *pyxc_vbd_setextents(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    PyObject *list, *dict, *obj;
+
+    unsigned int    dom, vbd;
+    xc_vbdextent_t *extents = NULL;
+    int             ret, i, nr_extents;
+
+    static char *kwd_list[] = { "dom", "vbd", "extents", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iio", kwd_list, 
+                                      &dom, &vbd, &list) )
+        goto fail;
+
+    if ( (nr_extents = PyList_Size(list)) < 0 )
+        goto fail;
+
+    if ( nr_extents != 0 )
+    {
+        extents = malloc(nr_extents * sizeof(xc_vbdextent_t));
+        if ( extents == NULL )
+            goto fail;
+
+        for ( i = 0; i < nr_extents; i++ )
+        {
+            dict = PyList_GetItem(list, i);
+            if ( !PyDict_Check(dict) )
+                goto fail;
+            if ( ((obj = PyDict_GetItemString(dict, "device")) == NULL) ||
+                 !PyInt_Check(obj) )
+                goto fail;
+            extents[i].real_device = (unsigned short)PyInt_AsLong(obj);
+            if ( ((obj = PyDict_GetItemString(dict,"start_sector")) == NULL) ||
+                 !PyInt_Check(obj) )
+                goto fail;
+            extents[i].start_sector = PyInt_AsLong(obj);
+            if ( ((obj = PyDict_GetItemString(dict, "nr_sectors")) == NULL) ||
+                 !PyInt_Check(obj) )
+                goto fail;
+            extents[i].nr_sectors = PyInt_AsLong(obj);        
+        }
+    }
+
+    ret = xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents);
+    
+    if ( extents != NULL )
+        free(extents);
     
     return PyInt_FromLong(ret);
+
+ fail:
+    if ( extents != NULL )
+        free(extents);
+    return NULL;
+}
+
+#define MAX_EXTENTS 1024
+static PyObject *pyxc_vbd_getextents(PyObject *self,
+                                     PyObject *args,
+                                     PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    PyObject *list;
+
+    unsigned int    dom, vbd;
+    xc_vbdextent_t *extents;
+    int             i, nr_extents, max_extents;
+
+    static char *kwd_list[] = { "dom", "vbd", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, 
+                                      &dom, &vbd) )
+        return NULL;
+
+    extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t));
+    if ( extents == NULL )
+        max_extents = 0;
+    else
+        max_extents = MAX_EXTENTS;
+
+    nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, max_extents,
+                                   extents, NULL);
+    
+    if ( nr_extents <= 0 )
+    {
+        list = PyList_New(0);
+    }
+    else
+    {
+        list = PyList_New(nr_extents);
+        for ( i = 0; i < nr_extents; i++ )
+        {
+            PyList_SetItem(
+                list, i, 
+                Py_BuildValue("{s:i,s:l,s:l}",
+                              "device",       extents[i].real_device,
+                              "start_sector", extents[i].start_sector,
+                              "nr_sectors",   extents[i].nr_sectors));
+        }
+    }
+
+    if ( extents != NULL )
+        free(extents);
+    
+    return list;
 }
 
 static PyObject *pyxc_vbd_probe(PyObject *self,
@@ -647,10 +754,10 @@ static PyMethodDef pyxc_methods[] = {
       " vbd       [int]: Identifier of the VBD.\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
-    { "vbd_add_extent", 
-      (PyCFunction)pyxc_vbd_add_extent
+    { "vbd_grow", 
+      (PyCFunction)pyxc_vbd_grow
       METH_VARARGS | METH_KEYWORDS, "\n"
-      "Add an extent to a virtual block device.\n"
+      "Grow a virtual block device by appending a new extent.\n"
       " dom          [int]: Identifier of domain containing the VBD.\n"
       " vbd          [int]: Identifier of the VBD.\n"
       " device       [int]: Identifier of the real underlying block device.\n"
@@ -658,17 +765,37 @@ static PyMethodDef pyxc_methods[] = {
       " nr_sectors   [int]: Length, in sectors, of this extent.\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
-    { "vbd_delete_extent", 
-      (PyCFunction)pyxc_vbd_delete_extent, 
+    { "vbd_shrink", 
+      (PyCFunction)pyxc_vbd_shrink, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Shrink a virtual block device by deleting its final extent.\n"
+      " dom          [int]: Identifier of domain containing the VBD.\n"
+      " vbd          [int]: Identifier of the VBD.\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "vbd_setextents", 
+      (PyCFunction)pyxc_vbd_setextents, 
       METH_VARARGS | METH_KEYWORDS, "\n"
-      "Delete an extent from a virtual block device.\n"
+      "Set all the extent information for a virtual block device.\n"
       " dom          [int]: Identifier of domain containing the VBD.\n"
       " vbd          [int]: Identifier of the VBD.\n"
-      " device       [int]: Identifier of the real underlying block device.\n"
-      " start_sector [int]: Real start sector of the extent.\n"
-      " nr_sectors   [int]: Length, in sectors, of the extent.\n\n"
+      " extents      [list of dicts]: Per-extent information.\n"
+      "  device       [int]: Identifier of the real underlying block device.\n"
+      "  start_sector [int]: Real start sector of this extent.\n"
+      "  nr_sectors   [int]: Length, in sectors, of this extent.\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
+    { "vbd_getextents", 
+      (PyCFunction)pyxc_vbd_getextents, 
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Get info on all the extents in a virtual block device.\n"
+      " dom          [int]: Identifier of domain containing the VBD.\n"
+      " vbd          [int]: Identifier of the VBD.\n\n"
+      "Returns: [list of dicts] per-extent information; empty on error.\n"
+      " device       [int]: Identifier of the real underlying block device.\n"
+      " start_sector [int]: Real start sector of this extent.\n"
+      " nr_sectors   [int]: Length, in sectors, of this extent.\n" },
+
     { "vbd_probe", 
       (PyCFunction)pyxc_vbd_probe, 
       METH_VARARGS | METH_KEYWORDS, "\n"
index 78ba3c86b9ff114390a9d6f6a4999dc099107e17..5103d85ffdf7797a8e4d178c7f0e755faaf51f5e 100644 (file)
@@ -274,14 +274,19 @@ long do_block_io_op(block_io_op_t *u_block_io_op)
        ret = vbd_create(&op.u.create_params); 
        break; 
 
-    case BLOCK_IO_OP_VBD_ADD:  
-       /* add an extent to a VBD */
-       ret = vbd_add(&op.u.add_params); 
+    case BLOCK_IO_OP_VBD_GROW:  
+       /* append an extent to a VBD */
+       ret = vbd_grow(&op.u.grow_params); 
        break; 
 
-    case BLOCK_IO_OP_VBD_REMOVE:  
-       /* remove an extent from a VBD */
-       ret = vbd_remove(&op.u.remove_params); 
+    case BLOCK_IO_OP_VBD_SHRINK:  
+       /* remove teh final extent from a VBD */
+       ret = vbd_shrink(&op.u.shrink_params); 
+       break; 
+
+    case BLOCK_IO_OP_VBD_SET_EXTENTS:  
+       /* a fresh extent list for the given VBD */
+       ret = vbd_setextents(&op.u.setextents_params); 
        break; 
 
     case BLOCK_IO_OP_VBD_DELETE:  
index 8607071b1be8ed41d382ab290c17ef0e84e2d133..f16adb6795bea5b983dea7417ffa6f5c2fa690d0 100644 (file)
@@ -33,6 +33,7 @@ extern int scsi_probe_devices(xen_disk_info_t *xdi);
 /* XXX SMH: crappy 'hash function' .. fix when care. */
 #define HSH(_x) ((_x) & (VBD_HTAB_SZ - 1))
 
+
 /* 
 ** Create a new VBD; all this involves is adding an entry to the domain's
 ** vbd hash table; caller must be privileged. 
@@ -43,10 +44,10 @@ long vbd_create(vbd_create_t *create)
     vbd_t *new_vbd, **pv; 
     long ret = 0;
 
-    if( !IS_PRIV(current) )
+    if ( unlikely(!IS_PRIV(current)) )
         return -EPERM; 
 
-    if ( (p = find_domain_by_id(create->domain)) == NULL )
+    if ( unlikely((p = find_domain_by_id(create->domain)) == NULL) )
     {
         DPRINTK("vbd_create attempted for non-existent domain %d\n", 
                 create->domain); 
@@ -59,7 +60,7 @@ long vbd_create(vbd_create_t *create)
           *pv != NULL; 
           pv = &(*pv)->next ) 
     {
-        if ( (*pv)->vdevice == create->vdevice )
+        if ( unlikely((*pv)->vdevice == create->vdevice) )
         {
             DPRINTK("vbd_create attempted for already existing vbd\n");
             ret = -EINVAL;
@@ -69,10 +70,16 @@ long vbd_create(vbd_create_t *create)
             break;
     }
 
-    new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL); 
+    if ( unlikely((new_vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) )
+    {
+        DPRINTK("vbd_create: out of memory\n");
+        ret = -ENOMEM;
+        goto out;
+    }
+
     new_vbd->vdevice = create->vdevice; 
     new_vbd->mode    = create->mode; 
-    new_vbd->extents = (xen_extent_le_t *)NULL; 
+    new_vbd->extents = NULL; 
     new_vbd->next    = *pv; 
 
     *pv = new_vbd;
@@ -83,44 +90,48 @@ long vbd_create(vbd_create_t *create)
     return ret; 
 }
 
-/*
-** Add an extent to an existing VBD; fails if the VBD doesn't exist. 
-** Doesn't worry about overlapping extents (e.g. merging etc) for now. 
-*/
-long vbd_add(vbd_add_t *add) 
+
+/* Grow a VBD by appending a new extent. Fails if the VBD doesn't exist. */
+long vbd_grow(vbd_grow_t *grow) 
 {
     struct task_struct *p; 
     xen_extent_le_t **px, *x; 
     vbd_t *v; 
     long ret = 0;
 
-    if ( !IS_PRIV(current) )
+    if ( unlikely(!IS_PRIV(current)) )
         return -EPERM; 
 
-    if ( (p = find_domain_by_id(add->domain)) == NULL )
+    if ( unlikely((p = find_domain_by_id(grow->domain)) == NULL) )
     {
-        DPRINTK("vbd_add attempted for non-existent domain %d\n", 
-                add->domain); 
+        DPRINTK("vbd_grow: attempted for non-existent domain %d\n", 
+                grow->domain); 
         return -EINVAL; 
     }
 
     spin_lock(&p->vbd_lock);
 
-    for ( v = p->vbdtab[HSH(add->vdevice)]; v != NULL; v = v->next ) 
-        if ( v->vdevice == add->vdevice )
+    for ( v = p->vbdtab[HSH(grow->vdevice)]; v != NULL; v = v->next ) 
+        if ( v->vdevice == grow->vdevice )
             break; 
 
-    if ( v == NULL )
+    if ( unlikely(v == NULL) )
     {
-        DPRINTK("vbd_add; attempted to add extent to non-existent VBD.\n"); 
+        DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n");
         ret = -EINVAL;
         goto out; 
     }
 
-    x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL); 
-    x->extent.device       = add->extent.device; 
-    x->extent.start_sector = add->extent.start_sector; 
-    x->extent.nr_sectors   = add->extent.nr_sectors; 
+    if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL)) == NULL) )
+    {
+        DPRINTK("vbd_grow: out of memory\n");
+        ret = -ENOMEM;
+        goto out;
+    }
+    x->extent.device       = grow->extent.device; 
+    x->extent.start_sector = grow->extent.start_sector; 
+    x->extent.nr_sectors   = grow->extent.nr_sectors; 
     x->next                = (xen_extent_le_t *)NULL; 
 
     for ( px = &v->extents; *px != NULL; px = &(*px)->next ) 
@@ -134,7 +145,8 @@ long vbd_add(vbd_add_t *add)
     return ret;
 }
 
-long vbd_remove(vbd_remove_t *remove) 
+
+long vbd_shrink(vbd_shrink_t *shrink)
 {
     struct task_struct *p; 
     xen_extent_le_t **px, *x; 
@@ -144,48 +156,126 @@ long vbd_remove(vbd_remove_t *remove)
     if ( !IS_PRIV(current) )
         return -EPERM; 
 
-    if ( (p = find_domain_by_id(remove->domain)) == NULL )
+    if ( (p = find_domain_by_id(shrink->domain)) == NULL )
     {
-        DPRINTK("vbd_remove attempted for non-existent domain %d\n", 
-                remove->domain); 
+        DPRINTK("vbd_shrink attempted for non-existent domain %d\n", 
+                shrink->domain); 
         return -EINVAL; 
     }
 
     spin_lock(&p->vbd_lock);
 
-    for ( v = p->vbdtab[HSH(remove->vdevice)]; v != NULL; v = v->next ) 
-        if ( v->vdevice == remove->vdevice )
+    for ( v = p->vbdtab[HSH(shrink->vdevice)]; v != NULL; v = v->next ) 
+        if ( v->vdevice == shrink->vdevice )
             break; 
 
-    if ( v == NULL )
+    if ( unlikely(v == NULL) || unlikely(v->extents == NULL) )
     {
-        DPRINTK("vbd_remove; attempt to remove ext from non-existent VBD.\n"); 
+        DPRINTK("vbd_shrink: attempt to remove non-existent extent.\n"); 
         ret = -EINVAL;
         goto out;
     }
 
-    for ( px = &v->extents; *px != NULL; px = &(*px)->next ) 
-        if ( (*px)->extent.start_sector == remove->extent.start_sector )
-            break;
-    
-    if ( ((x = *px) == NULL) || 
-         (x->extent.nr_sectors != remove->extent.nr_sectors) || 
-         (x->extent.device != remove->extent.device) )
+    /* Find the last extent. We now know that there is at least one. */
+    for ( px = &v->extents; (*px)->next != NULL; px = &(*px)->next )
+        continue;
+
+    x   = *px;
+    *px = x->next;
+    kfree(x);
+
+ out:
+    spin_unlock(&p->vbd_lock);
+    put_task_struct(p);
+    return ret; 
+}
+
+
+long vbd_setextents(vbd_setextents_t *setextents)
+{
+    struct task_struct *p; 
+    xen_extent_t e;
+    xen_extent_le_t *new_extents, *x, *t; 
+    vbd_t *v; 
+    int i;
+    long ret = 0;
+
+    if ( !IS_PRIV(current) )
+        return -EPERM; 
+
+    if ( (p = find_domain_by_id(setextents->domain)) == NULL )
+    {
+        DPRINTK("vbd_setextents attempted for non-existent domain %d\n", 
+                setextents->domain); 
+        return -EINVAL; 
+    }
+
+    spin_lock(&p->vbd_lock);
+
+    for ( v = p->vbdtab[HSH(setextents->vdevice)]; v != NULL; v = v->next ) 
+        if ( v->vdevice == setextents->vdevice )
+            break; 
+
+    if ( unlikely(v == NULL) )
     {
-        DPRINTK("vbd_remove: attempt to remove non-matching extent.\n");
+        DPRINTK("vbd_setextents: attempt to modify non-existent VBD.\n"); 
         ret = -EINVAL;
         goto out;
     }
 
-    *px = x->next;
-    kfree(x);
+    /* Construct the new extent list. */
+    new_extents = NULL;
+    for ( i = setextents->nr_extents; i >= 0; i++ )
+    {
+        if ( unlikely(copy_from_user(&e, 
+                                     &setextents->extents[i], 
+                                     sizeof(e)) != 0) )
+        {
+            DPRINTK("vbd_setextents: copy_from_user failed\n");
+            ret = -EFAULT;
+            goto free_and_out;
+        }
+        
+        if ( unlikely((x = kmalloc(sizeof(xen_extent_le_t), GFP_KERNEL))
+                      == NULL) )
+        {
+            DPRINTK("vbd_setextents: out of memory\n");
+            ret = -ENOMEM;
+            goto free_and_out;
+        }
+        
+        x->extent = e;
+        x->next   = new_extents;
+
+        new_extents = x;
+    }
+
+    /* Delete the old extent list _after_ successfully creating the new. */
+    for ( x = v->extents; x != NULL; x = t )
+    {
+        t = x->next;
+        kfree(x);
+    }
+
+    /* Make the new list visible. */
+    v->extents = new_extents;
 
  out:
     spin_unlock(&p->vbd_lock);
     put_task_struct(p);
-    return ret; 
+    return ret;
+
+ free_and_out:
+    /* Failed part-way through the new list. Delete all that we managed. */
+    for ( x = new_extents; x != NULL; x = t )
+    {
+        t = x->next;
+        kfree(x);
+    }
+    goto out;
 }
 
+
 long vbd_delete(vbd_delete_t *delete) 
 {
     struct task_struct *p; 
@@ -442,6 +532,8 @@ long vbd_info(vbd_info_t *info)
     extents = info->extents;
     for ( x = v->extents; x != NULL; x = x->next )
     {
+        if ( info->nextents == info->maxextents )
+            break;
         if ( copy_to_user(extents, &x->extent, sizeof(xen_extent_t)) )
         {
             DPRINTK("vbd_info: copy_to_user failed\n");
@@ -449,7 +541,7 @@ long vbd_info(vbd_info_t *info)
             goto out; 
         } 
         extents++;
-        info->nextents++; 
+        info->nextents++;
     }
 
  out: 
index e6dc6dafd6c8a3d8f50c3d3af08e9ac2281bde54..df3ecba4ca966dc7e072d3effe5aa5e0b3a7f6d9 100644 (file)
@@ -6,25 +6,24 @@
  * Block I/O trap operations and associated structures.
  */
 
-#define BLOCK_IO_OP_SIGNAL       0    /* let xen know we have work to do */ 
+#define BLOCK_IO_OP_SIGNAL       0    /* let xen know we have work to do     */
 #define BLOCK_IO_OP_RESET        1    /* reset ring indexes on quiescent i/f */
 #define BLOCK_IO_OP_RING_ADDRESS 2    /* returns machine address of I/O ring */
 #define BLOCK_IO_OP_VBD_CREATE   3    /* create a new VBD for a given domain */
-#define BLOCK_IO_OP_VBD_ADD      4    /* add an extent to a given VBD */
-#define BLOCK_IO_OP_VBD_REMOVE   5    /* remove an extent from a given VBD */
-#define BLOCK_IO_OP_VBD_DELETE   6    /* delete a VBD */
-#define BLOCK_IO_OP_VBD_PROBE    7    /* query VBD information for a domain */
-#define BLOCK_IO_OP_VBD_INFO     8    /* query info about a particular VBD */
+#define BLOCK_IO_OP_VBD_GROW     4    /* append an extent to a given VBD     */
+#define BLOCK_IO_OP_VBD_SHRINK   5    /* remove last extent from a given VBD */
+#define BLOCK_IO_OP_VBD_SET_EXTENTS 6 /* provide a fresh extent list for VBD */
+#define BLOCK_IO_OP_VBD_DELETE   7    /* delete a VBD */
+#define BLOCK_IO_OP_VBD_PROBE    8    /* query VBD information for a domain */
+#define BLOCK_IO_OP_VBD_INFO     9    /* query info about a particular VBD */
 
 typedef struct _xen_extent { 
     u16       device; 
-    u16       unused;                 // pad 
+    u16       unused;
     ulong     start_sector; 
     ulong     nr_sectors;
 } xen_extent_t; 
 
-
-
 #define VBD_MODE_R         0x1
 #define VBD_MODE_W         0x2
 
@@ -33,44 +32,49 @@ typedef struct _xen_extent {
 
   
 typedef struct _vbd_create { 
-    unsigned     domain;              // create VBD for this domain 
-    u16          vdevice;             // 16 bit id domain will refer to VBD as 
-    u16          mode;                // OR of { VBD_MODE_R , VBD_MODE_W } 
+    unsigned     domain;              /* create VBD for this domain */
+    u16          vdevice;             /* id by which dom will refer to VBD */ 
+    u16          mode;                /* OR of { VBD_MODE_R , VBD_MODE_W } */
 } vbd_create_t; 
 
-typedef struct _vbd_add { 
-    unsigned     domain;              // domain in question 
-    u16          vdevice;             // 16 bit id domain refers to VBD as 
-    xen_extent_t extent;              // the extent to add to this VBD
-} vbd_add_t; 
+typedef struct _vbd_grow { 
+    unsigned     domain;              /* domain in question */
+    u16          vdevice;             /* 16 bit id domain refers to VBD as */
+    xen_extent_t extent;              /* the extent to add to this VBD */
+} vbd_grow_t; 
 
-typedef struct _vbd_remove { 
-    unsigned     domain;              // domain in question 
-    u16          vdevice;             // 16 bit id domain refers to VBD as 
-    xen_extent_t extent;              // the extent to remove from this VBD
-} vbd_remove_t; 
+typedef struct _vbd_shrink { 
+    unsigned     domain;              /* domain in question */
+    u16          vdevice;             /* 16 bit id domain refers to VBD as */
+} vbd_shrink_t; 
 
+typedef struct _vbd_setextents { 
+    unsigned     domain;              /* domain in question */
+    u16          vdevice;             /* 16 bit id domain refers to VBD as */
+    u16          nr_extents;          /* number of extents in the list */
+    xen_extent_t *extents;            /* the extents to add to this VBD */
+} vbd_setextents_t; 
 
 typedef struct _vbd_delete {          
-    unsigned     domain;              // domain in question 
-    u16          vdevice;             // 16 bit id domain refers to VBD as 
+    unsigned     domain;              /* domain in question */
+    u16          vdevice;             /* 16 bit id domain refers to VBD as */
 } vbd_delete_t; 
 
 #define VBD_PROBE_ALL 0xFFFFFFFF
 typedef struct _vbd_probe { 
-    unsigned         domain;          // domain in question or VBD_PROBE_ALL
-    xen_disk_info_t  xdi;             // where's our space for VBD/disk info
+    unsigned         domain;          /* domain in question or VBD_PROBE_ALL */
+    xen_disk_info_t  xdi;             /* where's our space for VBD/disk info */
 } vbd_probe_t; 
 
 typedef struct _vbd_info { 
     /* IN variables  */
-    unsigned      domain;             // domain in question 
-    u16           vdevice;            // 16 bit id domain refers to VBD as 
-    u16           maxextents;         // max no. of extents to return info for
-    xen_extent_t *extents;            // pointer to space for array of extents
+    unsigned      domain;             /* domain in question */
+    u16           vdevice;            /* 16 bit id domain refers to VBD as */ 
+    u16           maxextents;         /* max # of extents to return info for */
+    xen_extent_t *extents;            /* pointer to space for extent list */
     /* OUT variables */
-    u16           nextents;           // no of extents in the above  
-    u16           mode;               // VBD_MODE_{READONLY,READWRITE}
+    u16           nextents;           /* # extents in the above list */
+    u16           mode;               /* VBD_MODE_{READONLY,READWRITE} */
 } vbd_info_t; 
 
 
@@ -81,13 +85,14 @@ typedef struct block_io_op_st
     {
         /* no entry for BLOCK_IO_OP_SIGNAL */
         /* no entry for BLOCK_IO_OP_RESET  */
-       unsigned long ring_mfn; 
-       vbd_create_t  create_params; 
-       vbd_add_t     add_params; 
-       vbd_remove_t  remove_params; 
-       vbd_delete_t  delete_params; 
-       vbd_probe_t   probe_params; 
-       vbd_info_t    info_params; 
+       unsigned long    ring_mfn; 
+       vbd_create_t     create_params; 
+       vbd_grow_t       grow_params; 
+       vbd_shrink_t     shrink_params; 
+       vbd_setextents_t setextents_params; 
+       vbd_delete_t     delete_params; 
+       vbd_probe_t      probe_params; 
+       vbd_info_t       info_params; 
     }
     u;
 } block_io_op_t;
index f5fc383fcd53f613c297a552ca7038cde014a27b..67345494186e451f7612d33d832e4084482e3b5f 100644 (file)
@@ -1,8 +1,8 @@
 /*
 ** include/xeno/vbd.h: 
 ** -- xen internal declarations + prototypes for virtual block devices
-**
 */
+
 #ifndef __VBD_H__
 #define __VBD_H__
 
@@ -11,8 +11,8 @@
 
 /* an entry in a list of xen_extent's */
 typedef struct _xen_extent_le { 
-    xen_extent_t           extent;     // an individual extent  
-    struct _xen_extent_le *next;       // and a pointer to the next 
+    xen_extent_t           extent;     /* an individual extent */
+    struct _xen_extent_le *next;       /* and a pointer to the next */ 
 } xen_extent_le_t; 
 
 
@@ -22,17 +22,18 @@ typedef struct _xen_extent_le {
 ** Each domain has a hash table to map from these to the relevant VBD. 
 */
 typedef struct _vbd { 
-    unsigned short    vdevice;   // what the domain refers to this vbd as 
-    unsigned short    mode;      // VBD_MODE_{READONLY,READWRITE}
-    xen_extent_le_t  *extents;   // list of xen_extents making up this vbd
-    struct _vbd      *next;      // for chaining in the hash table
+    unsigned short    vdevice;   /* what the domain refers to this vbd as */
+    unsigned short    mode;      /* VBD_MODE_{READONLY,READWRITE} */
+    xen_extent_le_t  *extents;   /* list of xen_extents making up this vbd */
+    struct _vbd      *next;      /* for chaining in the hash table */
 } vbd_t; 
 
-#define VBD_HTAB_SZ  16       // no. of entries in the vbd hash table. 
+#define VBD_HTAB_SZ  16       /* # entries in the vbd hash table. */
 
 long vbd_create(vbd_create_t *create_params); 
-long vbd_add(vbd_add_t *add_params); 
-long vbd_remove(vbd_remove_t *remove_params);
+long vbd_grow(vbd_grow_t *grow_params); 
+long vbd_shrink(vbd_shrink_t *shrink_params);
+long vbd_setextents(vbd_setextents_t *setextents_params);
 long vbd_delete(vbd_delete_t *delete_params); 
 long vbd_probe(vbd_probe_t *probe_params); 
 long vbd_info(vbd_info_t *info_params); 
@@ -50,5 +51,4 @@ typedef struct {
 
 int vbd_translate(phys_seg_t *pseg, struct task_struct *p, int operation); 
 
-
 #endif /* __VBD_H__ */